#ifndef _topic_messenger_H__
#define _topic_messenger_H__

#ifdef __cplusplus
extern "C"
{
#endif

#include "topic_messenger_conf.h"

#ifdef topic_messenger_lib_en
#define topic_messenger_compile_en true
#endif
#if topic_messenger_compile_en

    typedef void (*topic_messenger_cb_t)(void *userdata, size_t lenth);

    typedef struct _topic_messenger_subscribe_t
    {

        uint16_t key_sum;
        uint8_t same_flag : 1;
        uint8_t priority : 2;
        uint8_t reserved : 5;
        const char *key;
        topic_messenger_cb_t _cb;
        struct _topic_messenger_subscribe_t *next;
        struct _topic_messenger_subscribe_t *last;
        struct _topic_messenger_subscribe_t *same_next;
        struct _topic_messenger_subscribe_t *same_last;
    } topic_messenger_subscribe_t;

    typedef struct _topic_messenger_list_t
    {
        void *userdata;
        struct _topic_messenger_list_t *next;
        size_t lenth;
    } topic_messenger_list_struct_t;

    typedef struct _topic_messenger_list_paras_t
    {
        topic_messenger_list_struct_t *head;
        size_t node_cnt; // 节点数量
    } topic_messenger_list_paras_t;

#if topic_messenger_support_rtos
    typedef struct
    {
        void (*mutex_get_cb)();
        void (*mutex_give_cb)();
    } topic_messenger_mutex_cb_t;
#endif

    typedef topic_messenger_subscribe_t *topic_messenger_handle_t;
    typedef topic_messenger_list_paras_t *topic_messenger_list_t;

#if (topic_messenger_support_rtos && !topic_messenger_platform_esp)
    /**
     * @brief 注册线程锁回调函数
     *
     * @param cb 获取，归还钥匙的回调函数
     */
    topic_messenger_ret_t topic_messenger_mutex_register(topic_messenger_mutex_cb_t *cb);
#endif

    /**
     * @brief 注册(订阅)有指定主题发布时的回调函数
     *
     * @param handle 用于接收返回句柄
     * @param theme 主题
     * @param cb 回调函数
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_subscribe(topic_messenger_handle_t *handle, const char *theme, topic_messenger_cb_t cb);

    /**
     * @brief 获取当前订阅的主题数量
     *
     * @return uint16_t
     */
    uint16_t topic_messenger_subscribe_count();

    /**
     * @brief 设置指定注册主题的优先级
     *
     * @param handle 句柄主题二选一，不使用的填NULL
     * @param theme 句柄主题二选一，不使用的填NULL
     * @param priority 优先级
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_set_priority(topic_messenger_handle_t handle, const char *theme, topic_messenger_priority_t priority);

    /**
     * @brief 注销单个已注册的主题订阅
     *
     * @param handle 注册的句柄
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_del(topic_messenger_handle_t handle);

    /**
     * @brief 注销所有已注册的指定主题订阅
     *
     * @param theme
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_del_by_theme(const char *theme);

    /**
     * @brief 注销所有已注册的订阅
     *
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_del_all();

    /**
     * @brief 发布一条主题通知
     *
     * @param theme 主题，可以是动态的
     * @param userdata 指向数据，可以是动态的，也可以是topic_messenger_list_t对象，用于一次性发送多组数据
     * @param lenth 数据长度，字节
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_msg(const char *theme, void *userdata, size_t lenth);

    ///////////////////////////////////////注意//////////////////////////////////////////////////
    // 在使用以下函数时，确保对同一个list的操作在同一个线程中，否则会导致致命错误
    /////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * @brief 创建一个数据列表
     *
     * @return topic_messenger_list_t 对象，NULL则创建失败
     */
    topic_messenger_list_t topic_messenger_list_create();

    /**
     * @brief 向数据列表中添加数据
     *
     * @param list 表对象
     * @param userdata 数据
     * @param lenth 数据长度
     *
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_list_add(topic_messenger_list_t list, void *userdata, size_t lenth);

    /**
     * @brief 获取数据列表中的数据数量
     *
     * @param list
     * @return size_t
     */
    size_t topic_messenger_list_get_cnt(topic_messenger_list_t list);

    /**
     * @brief 获取数据列表中的数据，一般用在事件回调函数中，数据获取后会自动销毁，列表自动移动到下一个数据
     * *       当所有节点被取出时，将自动销毁列表
     *
     * @param list 表对象
     * @param userdata 用于存储数据的容器
     * @param lenth 获取到的数据长度
     *
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_list_retrieve(topic_messenger_list_t list, void **userdata, size_t *lenth);

    /**
     * @brief 销毁数据列表所有数据和列表自身
     *
     * @param list
     * @return topic_messenger_ret_t
     */
    topic_messenger_ret_t topic_messenger_list_destroy(topic_messenger_list_t list);

#endif

#ifdef __cplusplus
}
#endif
#endif
